<?php
namespace GrouppaGroup;
class MCrypt
{
    private static $iv = 'groua08paSfvxcv3'; #Same as in JAVA
    private static $key = 'v0a8erce4SGzxn3c'; #Same as in JAVA

    /**
     * encrypts a string (utf-8 encoded)
     * @param  string $str string to be encrypted
     * @return string array of bytes converted to string array of hex values
     */
    public static function encrypt($str)
    {
        return bin2hex(self::encryptToBytes($str));
    }

    /**
     * encrypts a string (UTF-8 encoded) into an array of bytes
     * @param  string $str string to be encrypted
     * @return string array of bytes with encrypted string
     */
    public static function encryptToBytes($str)
    {

        if (strlen($str) == 0)
            return '';

        //adding 4 bytes with length of the string
        $length = strlen($str);
        $str = pack('N', $length) . $str;
        $iv = self::$iv;

        $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);

        mcrypt_generic_init($td, self::$key, $iv);
        $encrypted = mcrypt_generic($td, self::padString($str));

        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);

        return $encrypted;
    }

    /**
     * decrypts a string of hex representation of bytes which
     * together form an encrypted string
     * warning: return string is trimmed
     * @param  string $code hex representation of encoded string
     * @return string decoded string
     */
    public static function decrypt($code)
    {
        $code = self::hex2bin($code);

        return self::decryptFromBytes($code);
    }

    /**
     * decrypts an array of bytes representing an encrypted string
     * warning: return string is trimmed
     * @param  string $code array of bytes with encoded string
     * @return string decrypted string trimmed
     */
    public static function decryptFromBytes($code)
    {
        if ($code == '')
            return '';
        $iv = self::$iv;

        $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);

        mcrypt_generic_init($td, self::$key, $iv);
        $decrypted = mdecrypt_generic($td, $code);

        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);

        //readig unpadded string length
        $lenStr = substr($decrypted, 0, 4);
        $length = unpack('N', $lenStr)[1];

        return substr($decrypted, 4, $length);

    }

    protected static function hex2bin($hexdata)
    {
        $bindata = '';

        for ($i = 0; $i < strlen($hexdata); $i += 2) {
            $bindata .= chr(hexdec(substr($hexdata, $i, 2)));
        }

        return $bindata;
    }

    /**
     * Pads a string to a length of 16 multiply
     * @param  string $source
     * @return string
     */
    protected static function padString($source)
    {
        $length = strlen($source);
        if ($length % 16 == 0)
            return $source;
        $padLength = 16 - $length % 16;

        return $source . str_repeat(' ', $padLength);
    }
}
